package errorx

// 处理error, 主要是提供打印调用栈的功能

import (
	"context"
	"fmt"
	"github.com/go-errors/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"strings"
)

var (
	ErrBreakDelayWaiting = errors.New("break delay waiting") // 中断延迟处理等待
)

// Errorf 触发error, 打印调用栈
func Errorf(ctx context.Context, format string, a ...any) error {
	return Throw(ctx, fmt.Errorf(format, a...), 2)
}

// New 触发error, 打印调用栈
func New(ctx context.Context, msg string) error {
	return Throw(ctx, fmt.Errorf(msg), 2)
}

// Throw 捕获error, 打印调用栈, 返回wrap后的error
func Throw(ctx context.Context, err any, skip ...int) error {
	if err == nil {
		return nil
	}

	_skip := 1 // default
	if len(skip) > 0 {
		_skip = skip[0]
	}
	wrapErr := errors.Wrap(err, _skip)
	logx.WithContext(ctx).WithCallerSkip(_skip).Errorf("%s", PrintError(wrapErr))
	return wrapErr
}

// Catch 捕获error, 打印调用栈, 不返回error
func Catch(ctx context.Context, err any, skip ...int) {
	if err == nil {
		return
	}

	_skip := 1 // default
	if len(skip) > 0 {
		_skip = skip[0]
	}

	logx.WithContext(ctx).WithCallerSkip(_skip).Errorf("%s", PrintError(errors.Wrap(err, _skip)))
}

func PrintError(err *errors.Error) (ret string) {
	if err == nil {
		return
	}

	slStack := strings.Split(err.ErrorStack(), "\n")
	var msg string
	for i, str := range slStack {
		if i == 0 {
			if strings.HasPrefix(str, "*errors.errorString ") {
				str = str[20:]
			}

			msg = str
			continue
		} else {
			ss := strings.Split(str, " ")
			if len(ss) > 0 {
				str = ss[0]
			}

			ss = strings.Split(str, ":")
			if len(ss) == 1 {
				continue
			}

			if ss[1] == "" {
				continue
			}
		}

		str = strings.TrimSpace(str)
		if str == "" {
			continue
		}

		if ret != "" {
			ret += "|"
		}

		ret += str
	}

	ret = fmt.Sprintf("%s [stack=%s]", msg, ret)

	return
}
